﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using DomainDriver.DomainModeling.Constraints;
using DomainDriver.DomainModeling.DataProviders;
using DomainDriver.DomainModeling.DomainModels;
using DomainDriver.DomainModeling.Exceptions;
using DomainDriver.DomainModeling.Repositories;
using DomainDriver.DomainModeling.Example;
using DomainDriver.DomainModeling.Example.DomainObjects;
using DomainDriver.DomainModeling.GenericUnitTesting;
using DomainDriver.DomainModeling.GenericUnitTesting.Constraints;
using DomainDriver.DomainModeling.Queries;

namespace DomainDriver.DomainModeling.UnitTests.Constraints
{
    [TestFixture(new object[] { DataSourcePersistenceType.None })]
    [TestFixture(new object[] { DataSourcePersistenceType.File })]
    [TestFixture(new object[] { DataSourcePersistenceType.Database })]
    public class EnumerationDomainObjectIndexConstraintTests : IndexConstraintTestFixture<ExampleDomainModel, EnumerationValue, EnumerationDomainObject>
    {
        private int m_CurrentEnumOption;

        public EnumerationDomainObjectIndexConstraintTests(DataSourcePersistenceType persistenceType)
            : base(persistenceType)
        {
            // do nothing
        }

        [SetUp]
        public override void SetUp()
        {
            base.SetUp();

            ICollection<EnumerationValue> keys = IndexedRepository.FindKeys();
            foreach (EnumerationValue key in keys)
            {
                IndexedRepository.Remove(key);
            }
            m_CurrentEnumOption = 0;
        }

        protected override ExampleDomainModel CreateDomainModel(DataSourcePersistenceType persistenceType, bool buildModelWithConstraints)
        {
            ExampleDomainModel model = new ExampleDomainModel(persistenceType, buildModelWithConstraints);
            return model;
        }

        protected override int GetIndexValue(EnumerationDomainObject domainObject)
        {
            return domainObject.Index;
        }

        protected override EnumerationDomainObject CreateDomainObjectWithCorrectIndexValue()
        {
            EnumerationDomainObject domainObject = new EnumerationDomainObject();
            int correctIndexValue = IndexConstraint.GetIndexValueForObject(domainObject);

            // NOTE: For testing index constraint still works without Index setter
            domainObject = new EnumerationDomainObject(m_CurrentEnumOption++, correctIndexValue);
            return domainObject;
        }

        protected override EnumerationDomainObject CreateDomainObjectWithIncorrectIndexValue(ref bool hasIndexSetter)
        {
            hasIndexSetter = false;
            EnumerationDomainObject domainObject = new EnumerationDomainObject(m_CurrentEnumOption++, -100);
            return domainObject;
        }

        protected override void UpdateDomainObjectIndex(EnumerationDomainObject domainObject, ref bool hasIndexSetter)
        {
            hasIndexSetter = false;
        }

        protected override void CreateMultipleObjects()
        {
            EnumerationDomainObject domainObject1 = CreateDomainObjectWithCorrectIndexValue();
            IndexedRepository.Add(domainObject1);

            EnumerationDomainObject domainObject2 = CreateDomainObjectWithCorrectIndexValue();
            IndexedRepository.Add(domainObject2);

            EnumerationDomainObject domainObject3 = CreateDomainObjectWithCorrectIndexValue();
            IndexedRepository.Add(domainObject3);

            m_RootLevelKeys.Add(domainObject1.Key);
            m_RootLevelKeys.Add(domainObject2.Key);
            m_RootLevelKeys.Add(domainObject3.Key);

            m_ChildrenPerRootLevelKey.Add(domainObject1.Key, 0);
            m_ChildrenPerRootLevelKey.Add(domainObject2.Key, 0);
            m_ChildrenPerRootLevelKey.Add(domainObject3.Key, 0);
        }

        protected override EnumerationDomainObject CreateChildObject(EnumerationValue parentDomainObjectKey)
        {
            EnumerationDomainObject domainObject = CreateDomainObjectWithCorrectIndexValue();
            return domainObject;
        }

        protected override IQuery<EnumerationDomainObject> GetQueryForRootObjects()
        {
            LinqQuery<EnumerationDomainObject> linqQuery = new LinqQuery<EnumerationDomainObject>((EnumerationDomainObject dObj) => true);

            return linqQuery;
        }
    }
}